<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>智能助手 - Ollama + Qwen-1.8B</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../lib/layui-v2.6.3/css/layui.css" media="all">
    <link rel="stylesheet" href="../../css/public.css" media="all">
    <style>
        * {
            box-sizing: border-box;
            transition: all 0.3s ease;
        }

        body {
            background: linear-gradient(135deg, #1a2a6c,#434459, #1a2a6c);
            background-size: 400% 400%;
            animation: gradientBG 15s ease infinite;
            color: #333;
            min-height: 100vh;
            padding: 20px;
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            line-height: 1.6;
        }

        @keyframes gradientBG {
            0% { background-position: 0% 50%; }
            50% { background-position: 100% 50%; }
            100% { background-position: 0% 50%; }
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        .header {
            text-align: center;
            margin-bottom: 30px;
            padding: 20px 0;
            background: rgba(255, 255, 255, 0.15);
            border-radius: 8px;
            color: white;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
            backdrop-filter: blur(10px);
        }

        .header h1 {
            font-size: 32px;
            margin-bottom: 10px;
            font-weight: 600;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 15px;
        }

        .header p {
            font-size: 16px;
            opacity: 0.9;
            max-width: 800px;
            margin: 0 auto;
        }

        .chat-container {
            background: rgba(255, 255, 255, 0.93);
            border-radius: 8px;
            box-shadow: 0 15px 50px rgba(0, 0, 0, 0.25);
            overflow: hidden;
            margin-bottom: 30px;
        }

        .chat-history {
            height: 450px;
            padding: 20px;
            overflow-y: auto;
            background-color: #fafafa;
            border-bottom: 1px solid #eee;
        }

        .message {
            margin-bottom: 20px;
            max-width: 80%;
            animation: fadeIn 0.4s ease;
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        .user-message {
            margin-left: auto;
            background: linear-gradient(135deg, #4facfe, #00f2fe);
            color: white;
            border-radius: 18px 18px 4px 18px;
        }

        .ai-message {
            background: #f5f5f5;
            border: 1px solid #e6e9ff;
            border-radius: 18px 18px 18px 4px;
        }

        .message-content {
            padding: 12px 16px;
            position: relative;
        }

        .message-avatar {
            width: 36px;
            height: 36px;
            border-radius: 50%;
            background: linear-gradient(135deg, #4facfe, #00f2fe);
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-right: 10px;
            flex-shrink: 0;
        }

        .ai-avatar {
            background: linear-gradient(135deg, #ff7e5f, #feb47b);
        }

        .message-header {
            display: flex;
            align-items: center;
            margin-bottom: 8px;
            font-weight: 600;
        }

        .message-text {
            line-height: 1.5;
        }

        .chat-input {
            padding: 20px;
            background: white;
        }

        .typing-indicator {
            display: none;
            padding: 10px 20px;
            color: #666;
            font-size: 14px;
            text-align: center;
        }

        .dots {
            display: inline-flex;
            gap: 6px;
            margin-left: 10px;
        }

        .dot {
            width: 10px;
            height: 10px;
            background: #1e88e5;
            border-radius: 50%;
            animation: bounce 1.4s infinite;
        }

        .dot:nth-child(2) {
            animation-delay: 0.2s;
        }

        .dot:nth-child(3) {
            animation-delay: 0.4s;
        }

        @keyframes bounce {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-8px); }
        }

        .input-container {
            display: flex;
            gap: 10px;
        }

        .input-container textarea {
            flex: 1;
            min-height: 80px;
            resize: none;
            padding: 12px 15px;
            border: 1px solid #ddd;
            border-radius: 6px;
            outline: none;
            font-size: 16px;
        }

        .input-container textarea:focus {
            border-color: #1e88e5;
            box-shadow: 0 0 0 2px rgba(30, 136, 229, 0.2);
        }

        .buttons {
            display: flex;
            justify-content: flex-end;
            gap: 10px;
            margin-top: 15px;
        }

        .btn {
            padding: 10px 20px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 8px;
            transition: all 0.3s;
        }

        .btn-send {
            background: #1e88e5;
            color: white;
        }

        .btn-send:hover {
            background: #1976d2;
            transform: translateY(-2px);
        }

        .btn-send:disabled {
            background: #90caf9;
            cursor: not-allowed;
            transform: none;
        }

        .btn-stop {
            background: #ff5252;
            color: white;
            display: none;
        }

        .btn-stop:hover {
            background: #e53935;
            transform: translateY(-2px);
        }

        .btn-clear {
            background: #f5f5f5;
            color: #666;
        }

        .btn-clear:hover {
            background: #e0e0e0;
        }

        .status-bar {
            display: flex;
            justify-content: space-between;
            padding: 15px 20px;
            background: #f5f5f5;
            border-top: 1px solid #eee;
            font-size: 14px;
            color: #666;
        }

        .system-info {
            display: flex;
            gap: 15px;
        }

        .info-item {
            display: flex;
            align-items: center;
            gap: 5px;
        }

        .info-item i {
            color: #1e88e5;
        }

        .message pre {
            background: #2d2d2d;
            color: #f8f8f2;
            padding: 10px;
            border-radius: 4px;
            overflow-x: auto;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            margin: 10px 0;
        }

        .message code {
            background: #f5f5f5;
            padding: 2px 4px;
            border-radius: 3px;
            font-family: 'Courier New', monospace;
        }

        .timestamp {
            font-size: 12px;
            color: #999;
            margin-top: 5px;
            text-align: right;
        }

        .ai-response {
            white-space: pre-wrap;
        }

        .welcome-message ul {
            padding-left: 20px;
            margin: 10px 0;
        }

        .welcome-message li {
            margin-bottom: 8px;
        }

        .message-text a {
            color: #1e88e5;
            text-decoration: none;
        }

        .message-text a:hover {
            text-decoration: underline;
        }

        .action-buttons {
            display: flex;
            justify-content: flex-end;
            margin-top: 10px;
            gap: 8px;
        }

        .action-btn {
            background: none;
            border: none;
            color: #666;
            cursor: pointer;
            font-size: 12px;
        }

        .action-btn:hover {
            color: #1e88e5;
        }

        @media (max-width: 768px) {
            .header h1 {
                font-size: 24px;
            }

            .chat-history {
                height: 400px;
            }

            .message {
                max-width: 90%;
            }

            .system-info {
                flex-wrap: wrap;
                gap: 8px;
            }
        }
    </style>
</head>
<body>
<div class="container">
    <div class="header">
        <h1><i class="fas fa-robot"></i> Ollama + Qwen-1.8B 智能助手</h1>
        <p>基于阿里云 CentOS 7.9 部署的智能问答系统，已连接您的 MySQL 数据库</p>
    </div>

    <div class="chat-container">
        <div class="chat-history" id="chatHistory">
            <div class="message ai-message">
                <div class="message-content">
                    <div class="message-header">
                        <div class="message-avatar ai-avatar">
                            <i class="fas fa-robot"></i>
                        </div>
                        <div>智能助手</div>
                    </div>
                    <div class="message-text welcome-message">
                        您好！我是您的数据库智能助手，你可以向我提出问题例如：
                        <ul>
                            <li>"今天的天气预报？"</li>
                            <li>"量子力学相关内容和解释"</li>
                            <li>"写一首韩梅梅,我喜欢你的藏头诗"</li>
                        </ul>
                        请问有什么可以帮您的？当您看到我回答时，可以随时点击"停止回答"按钮中断我的响应。
                    </div>
                    <div class="timestamp">系统消息</div>
                </div>
            </div>
        </div>

        <div class="typing-indicator" id="typingIndicator">
            <i class="fas fa-spinner fa-spin"></i> 正在思考中
            <div class="dots">
                <div class="dot"></div>
                <div class="dot"></div>
                <div class="dot"></div>
            </div>
        </div>

        <div class="chat-input">
            <div class="input-container">
                <textarea id="questionInput" placeholder="请输入您的问题..."></textarea>
            </div>
            <div class="buttons">
                <button class="btn btn-clear" id="clearButton">
                    <i class="fas fa-trash-alt"></i> 清空对话
                </button>
                <button class="btn btn-stop" id="stopButton">
                    <i class="fas fa-stop-circle"></i> 停止回答
                </button>
                <button class="btn btn-send" id="sendButton">
                    <i class="fas fa-paper-plane"></i> 发送
                </button>
            </div>
        </div>

        <div class="status-bar">
            <div class="system-info">
                <div class="info-item">
                    <i class="fas fa-database"></i> XX 已连接
                </div>
                <div class="info-item">
                    <i class="fas fa-server"></i> Ollama 服务运行中
                </div>
                <div class="info-item">
                    <i class="fas fa-brain"></i> Qwen-1.8B 模型已加载
                </div>
            </div>
            <div class="info-item">
                <i class="fas fa-bolt"></i> 流式传输已启用
            </div>
        </div>
    </div>
</div>

<script src="../../lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script>
    layui.use(['layer', 'jquery'], function(){
        var layer = layui.layer;
        var $ = layui.$;

        // 获取DOM元素
        const chatHistory = document.getElementById('chatHistory');
        const questionInput = document.getElementById('questionInput');
        const sendButton = document.getElementById('sendButton');
        const stopButton = document.getElementById('stopButton');
        const clearButton = document.getElementById('clearButton');
        const typingIndicator = document.getElementById('typingIndicator');

        // 全局变量
        let controller = null;
        let isStreaming = false;
        let currentAiMessage = null;

        // 添加消息到聊天历史
        function addMessage(content, isUser = false) {
            const messageDiv = document.createElement('div');
            messageDiv.className = `message ${isUser ? 'user-message' : 'ai-message'}`;

            const now = new Date();
            const timestamp = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;

            const avatarIcon = isUser ? 'fa-user' : 'fa-robot';
            const avatarClass = isUser ? '' : 'ai-avatar';
            const senderName = isUser ? '您' : '智能助手';

            messageDiv.innerHTML = `
          <div class="message-content">
            <div class="message-header">
              <div class="message-avatar ${avatarClass}">
                <i class="fas ${avatarIcon}"></i>
              </div>
              <div>${senderName}</div>
            </div>
            <div class="message-text ai-response">${content}</div>
            <div class="timestamp">${timestamp}</div>
          </div>
        `;

            chatHistory.appendChild(messageDiv);
            chatHistory.scrollTop = chatHistory.scrollHeight;
            return messageDiv;
        }

        // 停止当前回答
        function stopAnswering() {
            if (controller) {
                controller.abort();
                controller = null;
            }

            isStreaming = false;
            stopButton.style.display = 'none';
            typingIndicator.style.display = 'none';
            sendButton.disabled = false;
            questionInput.disabled = false;

            // 添加中断消息
            if (currentAiMessage) {
                const contentDiv = currentAiMessage.querySelector('.message-text');
                contentDiv.innerHTML += '<p><i>回答已停止</i></p>';
            }
        }

        // 发送问题到后端
        async function sendQuestion() {
            const question = questionInput.value.trim();
            if (!question) return;

            // 添加用户消息
            addMessage(question, true);

            // 清空输入框并禁用发送按钮
            questionInput.value = '';
            sendButton.disabled = true;
            questionInput.disabled = true;

            // 显示"正在思考"指示器和停止按钮
            typingIndicator.style.display = 'block';
            stopButton.style.display = 'flex';
            chatHistory.scrollTop = chatHistory.scrollHeight;

            try {
                // 创建AI消息容器
                currentAiMessage = addMessage('', false);
                const contentDiv = currentAiMessage.querySelector('.message-text');

                // 创建新的AbortController
                controller = new AbortController();
                isStreaming = true;

                // 发送请求到后端流式API
                const response = await fetch('/oll/ai/stream', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        question: question
                    }),
                    signal: controller.signal
                });

                if (!response.ok) {
                    throw new Error(`请求失败: ${response.status}`);
                }

                // 处理流式响应
                const reader = response.body.getReader();
                const decoder = new TextDecoder('utf-8');
                let aiResponse = '';

                while (isStreaming) {
                    const { done, value } = await reader.read();
                    if (done) break;

                    const chunk = decoder.decode(value, { stream: true });
                    aiResponse += chunk.replace(/data:/gi, "").replace(/\n/g, "");

                    // 更新AI消息内容
                    contentDiv.textContent = aiResponse;

                    // 滚动到最新内容
                    chatHistory.scrollTop = chatHistory.scrollHeight;
                }

                // 完成时添加最后的字符
                contentDiv.textContent = aiResponse;

            } catch (error) {
                if (error.name === 'AbortError') {
                    console.log('请求已被用户终止');
                } else {
                    console.error('请求出错:', error);
                    const errorDiv = document.createElement('div');
                    errorDiv.style.color = '#e53935';
                    errorDiv.textContent = `请求出错: ${error.message || '服务不可用'}`;
                    if (currentAiMessage) {
                        currentAiMessage.querySelector('.message-text').appendChild(errorDiv);
                    } else {
                        addMessage(errorDiv.outerHTML);
                    }
                }
            } finally {
                // 重置状态
                isStreaming = false;
                typingIndicator.style.display = 'none';
                stopButton.style.display = 'none';
                sendButton.disabled = false;
                questionInput.disabled = false;
                controller = null;

                // 聚焦到输入框
                questionInput.focus();
            }
        }

        // 清空对话
        function clearConversation() {
            chatHistory.innerHTML = `
          <div class="message ai-message">
            <div class="message-content">
              <div class="message-header">
                <div class="message-avatar ai-avatar">
                  <i class="fas fa-robot"></i>
                </div>
                <div>智能助手</div>
              </div>
              <div class="message-text welcome-message">
                对话已重置！您可以开始新的提问。
              </div>
              <div class="timestamp">系统消息</div>
            </div>
          </div>
        `;
        }

        // 事件监听器
        sendButton.addEventListener('click', sendQuestion);

        stopButton.addEventListener('click', stopAnswering);

        clearButton.addEventListener('click', clearConversation);

        questionInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendQuestion();
            }
        });

        // 初始化页面
        questionInput.focus();
    });
</script>
</body>
</html>
